package com.wzcl.app.config.oauth.authentication.mobile;

import com.alibaba.fastjson.JSON;
import com.wzcl.app.config.oauth.handler.MyAuthenticationFailureHandler;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.common.ValidateCode;
import com.wzcl.app.service.impl.RegisterServiceImpl;
import com.wzcl.app.utils.RedisUtil;
import com.wzcl.app.utils.SpringUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.core.AuthenticationException;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;


@EqualsAndHashCode(callSuper = true)
@Log4j2
@Data
public class SmsCodeFilter extends OncePerRequestFilter implements InitializingBean {

    private Set<String> urls = new HashSet<>();

    /**
     * 验证请求url与配置的url是否匹配的工具类
     */
    private AntPathMatcher pathMatcher = new AntPathMatcher();


    public SmsCodeFilter(){
    }

    /**
     * 初始化要拦截的url配置信息
     */
    @Override
    public void afterPropertiesSet() throws ServletException {
        super.afterPropertiesSet();
        urls.add("/authentication/mobile");
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {

        boolean action = false;
        for (String url : urls) {
            if (pathMatcher.match(url, request.getRequestURI())) {
                action = true;
            }
        }
        try {
        if (action){
            redisValidate(new ServletWebRequest(request));
        }
        }catch (AuthenticationException e) {
            Object myAuthenticationFailureHandler = SpringUtil.getBean("myAuthenticationFailureHandler");
            MyAuthenticationFailureHandler failureHandler = (MyAuthenticationFailureHandler) myAuthenticationFailureHandler;
            failureHandler.onAuthenticationFailure(request,response,e);
            return;
        }
        chain.doFilter(request,response);
    }

    private void redisValidate(ServletWebRequest request) throws ServletRequestBindingException {

        String mobile = request.getParameter("mobile");
        String codeInRequest = ServletRequestUtils.getStringParameter(request.getRequest(), "smsCode");
        if(StringUtils.isBlank(mobile) ||StringUtils.isBlank(codeInRequest)){
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL,"缺少手机号或验证码");
        }
        RedisUtil redisUtil = (RedisUtil) SpringUtil.getBean("redisUtil");
        Object o = redisUtil.get(mobile + RegisterServiceImpl.VALIDATE_CODE_KEY);
        if (null == o) {
            throw new BusinessException(CodeMsg.CODE_NOT_SEND);
        }
        ValidateCode validateCode = JSON.parseObject((String)o,ValidateCode.class);
        if(validateCode.isExpire()){
            redisUtil.del(mobile + RegisterServiceImpl.VALIDATE_CODE_KEY);
            throw new BusinessException(CodeMsg.CODE_NOT_SEND);
        }
        if (!validateCode.getCode().equals(codeInRequest)) {
            throw new BusinessException(CodeMsg.CODE_NOT_MATCH);
        }
        if(redisUtil.hasKey(mobile + RegisterServiceImpl.VALIDATE_CODE_LOCK)){
            redisUtil.del(mobile + RegisterServiceImpl.VALIDATE_CODE_LOCK);
        }
        redisUtil.del(mobile + RegisterServiceImpl.VALIDATE_CODE_KEY);
    }
}
